#define AUTOCFGSSID u8"瑞云一家"
#define USE_8266
#define USE_MQTT
#include <memory>
#include <Arduino.h>
#include "webCtrl.h"

#include "CDoCmd.h"
#include "BafaOTA.h"
#include "Boiler.h"
#include "ESP8266Bafayun.h"

#ifdef USE_MQTT
ESP8266BafayunBase *ESP8266Batayun = &ESP8266BafayunMQTT::getSingleton();
#else
ESP8266BafayunBase *ESP8266Batayun = &ESP8266BafayunTCP::getSingleton();
#endif

#define PIN_TEST 12
#define PIN_SWITCH 5

std::unique_ptr<CWebControl> g_WebControl;
CBoiler g_Boiler(PIN_TEST, PIN_SWITCH);

bool WebCtrlCallBack(const char *name)
{
    static CDoCmd &cmd = CDoCmd::getSingleton();
    return cmd.doCmd(String(name));
}

// 处理没有处理的命令
void do_othercmd(const String &cmd)
{
    if (cmd.startsWith("delay:") && cmd.length() > 6)
    {
        String strTime = cmd.substring(6);
        Serial.println("delay:" + strTime);
        uint32_t nDelay=strtoul(strTime.c_str(), nullptr, 10);
        CConfig::getSingleton().setDelay(nDelay);
        g_Boiler.setDelay(nDelay);
         Serial.println("delay:" + String(nDelay));
        CConfig::getSingleton().SaveConfig();
    }
}

void mqtt_callback(const char *topic, const char *payload, unsigned int len)
{
    if ((payload == nullptr) || (strncmp(payload, "S:", 2) == 0))
        return;
    String msg;
    if (strncmp(payload, "C:", 2) == 0)
    {
        msg.concat(payload + 2, len - 2);
    }
    else
    {
        msg.concat(payload, len);
    }
    Serial.print("msg_callback:");
    Serial.println(msg);
    // 执行命令
    static CDoCmd &cmd = CDoCmd::getSingleton();
    if (!cmd.doCmd(msg))
    {
        do_othercmd(msg);
    }
}

void setup()
{
    Serial.begin(115200);

    CDoCmd &cmd = CDoCmd::getSingleton();
    cmd.pushCmd("btn_turnon", [] // 网页上的开机
                {
        g_Boiler.TurnOn();
        Serial.println("btn_turnon"); });

    cmd.pushCmd("on", [] // 开机
                {
        g_Boiler.TurnOn();
        Serial.println("btn_turnon"); });

    cmd.pushCmd("ota", [] // ota升级
                {
        OTA ota;
        ota.updateFormOTA(); });

    cmd.pushCmd("btn_turnoff", [] // 配置网页上的关机
                {
        g_Boiler.turnOff();
        Serial.println("btn_turnoff"); });

    cmd.pushCmd("off", [] // 关机
                {
        g_Boiler.turnOff();
        Serial.println("btn_turnoff"); });

    cmd.pushCmd("isonline", [] // 是否在线
                {
        ESP8266Batayun->upload("S:" + String(g_Boiler.isPowerOn()));
        Serial.println("is_online"); });

    cmd.pushCmd("getconfig", [] // 获取配置目前只有延时
                {
        uint32_t nDelay=0;
        ESP8266Batayun->upload("S:" + String("delay:")+String(CConfig::getSingleton().GetDelay(nDelay)));
        Serial.println("getconfig"); });
    // put your setup code here, to run once:
    CConfig &config = CConfig::getSingleton();
    if (!config)
    {
        // 配置无效则打开web服务，提供配置
        g_WebControl = std::make_unique<CWebControl>();
        g_WebControl->init();
        g_WebControl->setCallBack(std::bind(WebCtrlCallBack, std::placeholders::_1));
        g_WebControl->run();
    }
    else
    {
        // 配置有效则连接网络
        String wifiap, wifipsw;
        config.GetWifiAP(wifiap);
        config.GetWifiPsw(wifipsw);

        Serial.println(wifiap);
        Serial.println(wifipsw);

        WiFi.mode(WIFI_STA);
        WiFi.begin(wifiap, wifipsw);
        WiFi.setAutoReconnect(true);
    }

    ESP8266Batayun->setMsgCallback(std::bind(mqtt_callback, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    ESP8266Batayun->init();
}

void loop()
{
    if (digitalRead(0) == LOW)
    {
        delay(3 * 1000); // BOOT三秒复位
        if (digitalRead(0) == LOW)
        {
            CConfig::getSingleton().Reset();
            ESP.restart();
        }
    }

    // put your main code here, to run repeatedly:
    if (g_WebControl != nullptr)
    {
        g_WebControl->loop();
    }
    static unsigned long preUnloadMsg = 0;
    if (millis() - preUnloadMsg >= 10 * 1000)
    {
        preUnloadMsg = millis();
        Serial.println(u8"上报数据");
        ESP8266Batayun->upload("S:" + String(g_Boiler.isPowerOn() ? "true" : "false"));
    }
    ESP8266Batayun->loop();
    g_Boiler.loop();
}